package com.appshelves.model;

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;

import com.appshelves.model.Model.Event;
import com.appshelves.model.Model.EventListener;

class EventGenerator {

    EnumMap<Event, EventSender> senders = new EnumMap<Event, EventSender>(Event.class);

    EventGenerator(EnumSet<Event> events) {
        initSenders(events);
    }

    ///

    void generateEvent(Event event) {
        getSender(event).sendEvent();
    }

    void generateEvent(Event event, Shelf shelf) {
        getSender(event).sendEvent(shelf);
    }

    void generateEvent(Event event, App app) {
        getSender(event).sendEvent(app);
    }

    void generateEvent(Event event, List<App> apps) {
        getSender(event).sendEvent(apps);
    }

    ///

    void addListener(Event event, EventListener listener) {
        getSender(event).addListener(listener);
    }

    boolean isListenerSet(Event event) {
        return getSender(event).listeners.size() != 0;
    }

    void removeListener(Event event, EventListener listener) {
        getSender(event).removeListener(listener);
    }

    void removeAllListeners() {
        for (EventSender sender : senders.values())
            sender.removeAllListeners();
    }

    ///

    private void initSenders(EnumSet<Event> events) {
        for (Event event : events)
            senders.put(event, new EventSender());
    }

    private EventSender getSender(Event event) {
        return senders.get(event);
    }

    ///

    static class EventSender {

        private List<EventListener> listeners = new ArrayList<EventListener>();

        void addListener(EventListener listener) {
            listeners.add(listener);
        }

        void removeListener(EventListener listener) {
            listeners.remove(listener);
        }

        void removeAllListeners() {
            listeners.clear();
        }

        void sendEvent() {
            sendToAll(null);
        }

        void sendEvent(Shelf shelf) {
            sendToAll(shelf);
        }

        void sendEvent(App app) {
            sendToAll(app);
        }

        void sendEvent(List<App> apps) {
            sendToAll(apps);
        }

        private void sendToAll(Object args) {
            for (EventListener listener : listeners)
                listener.onEvent(args);
        }

    }
}
